import java.util.Random;

import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.plugin.PlugIn;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;


public class test_Plugin implements PlugIn {

		static int W = 400;					// width of the new image
		static int H = 300;					// height of the new image
		
		static double xc = 200;				// x-center of the circle
		static double yc = 150;				// y-center of the circle
		static double rad = 100;			// radius of the circle
		
		static double xySigma = 0.5;		// standard variation of position noise
		static int onCirclePts = 150;		// number of points ON the circle
		static int offCirclePts = 100;		// number of additional random points 
		
		static String imageTitle = "circle-test";

		@Override
		public void run(String arg0) {
			if (!getUserInput()) {
				return;
			}
			
			// create a new grayscale image
			ImageProcessor ip = new ByteProcessor(W, H);
			ip.invertLut();					// to show white background
			
			Random rg = new Random();
			
			// create random points on the circle
			for (int i = 0; i < onCirclePts; i++) {
				double phi = rg.nextDouble() * 2 * Math.PI;	// uniformly distributed angle 0,...,2pi
				double dx = xySigma * rg.nextGaussian();	// position disturbed by Gaussian noise
				double dy = xySigma * rg.nextGaussian();
				int u = (int) Math.round(xc + rad * Math.cos(phi) + dx);
				int v = (int) Math.round(yc + rad * Math.sin(phi) + dy);
				ip.putPixel(u, v, 255);
			}
			
			// create additional random points uniformly distributed in the image
			for (int i = 0; i < offCirclePts; i++) {
				int u = rg.nextInt(W);
				int v = rg.nextInt(H);
				ip.putPixel(u, v, 255);
			}
			
			// display the new image
			(new ImagePlus(imageTitle, ip)).show();
			
		}
		
		boolean getUserInput() {
			GenericDialog gd = new GenericDialog("Create Circle Test Image");
			gd.addNumericField("Image width", W, 0);
			gd.addNumericField("Image height", H, 0);
			gd.addNumericField("Center xc", xc, 2);
			gd.addNumericField("Center yc", yc, 2);
			gd.addNumericField("Radius r", rad, 2);
			gd.addNumericField("Position Noise sigma", xySigma, 2);
			gd.addNumericField("No. of ON-Circle Points", onCirclePts, 0);
			gd.addNumericField("No. of OFF-Circle Points", offCirclePts, 0);
			gd.showDialog();
			if (gd.wasCanceled()) {
				return false;
			}
			W = (int) gd.getNextNumber();
			H = (int) gd.getNextNumber();
			xc = gd.getNextNumber();
			yc = gd.getNextNumber();
			rad = gd.getNextNumber();
			xySigma = gd.getNextNumber();
			onCirclePts = (int) gd.getNextNumber();
			offCirclePts = (int) gd.getNextNumber();
			return true;
		}

	}
